/**
 * Dateformat 日期格式化
 * @description 日期格式化组件
 * @tutorial https://ext.dcloud.net.cn/plugin?id=3279
 * @property {Object|String|Number} date 日期对象/日期字符串/时间戳
 * @property {String} locale 格式化使用的语言
 * 	@value zh 中文
 * 	@value en 英文
 * @property {Array} threshold 应用不同类型格式化的阈值
 * @property {String} format 输出日期字符串时的格式
 */
Component({
    properties: {
        date: {
            type: [Object, String, Number],
            value: '-'
        },
        locale: {
            type: String,
            value: 'zh',
        },
        threshold: {
            type: Array,
            value: [60000, 3600000]
        },
        format: {
            type: String,
            value: 'yyyy/MM/dd hh:mm:ss'
        },
        // refreshRate使用不当可能导致性能问题，谨慎使用
        refreshRate: {
            type: [Number, String],
            value: 0
        }
    },
    attached: function() {
        const that = this
        that.dateShow()
    },
    data: {
        dateShow: null
    },
    methods: {
        // yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型
        pad: function(str, length = 2) {
            str += ''
            while (str.length < length) {
                str = '0' + str
            }
            return str.slice(-length)
        },
        yyyy: function(dateObj) {
            const that = this
            return that.pad(dateObj.year, 4)
        },
        yy: function(dateObj) {
            return this.pad(dateObj.year)
        },
        MM: function(dateObj) {
            return this.pad(dateObj.month)
        },
        M: function(dateObj) {
            return dateObj.month
        },
        dd: function(dateObj) {
            return this.pad(dateObj.day)
        },
        d: function(dateObj) {
            return dateObj.day
        },
        hh: function(dateObj) {
            return this.pad(dateObj.hour)
        },
        h: function(dateObj) {
            return dateObj.hour
        },
        mm: function(dateObj) {
            return this.pad(dateObj.minute)
        },
        m: function(dateObj) {
            return dateObj.minute
        },
        ss: function(dateObj) {
            return this.pad(dateObj.second)
        },
        s: function(dateObj) {
            return dateObj.second
        },
        SSS: function(dateObj) {
            return this.pad(dateObj.millisecond, 3)
        },
        S: function(dateObj) {
            return dateObj.millisecond
        },
        dateShow: function() {
            const that = this
            const dateShow = that.friendlyDate(that.properties.date, {
                locale: that.properties.locale,
                threshold: that.properties.threshold,
                format: that.properties.format
            })
            that.setData({
                dateShow: dateShow
            })
        },
        // 这都n年了iOS依然不认识2020-12-12，需要转换为2020/12/12
        getDate: function (time) {
            if (time instanceof Date) {
                return time
            }
            switch (typeof time) {
                case 'string':  {
                    // 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000
                    if (time.indexOf('T') > -1) {
                        return new Date(time)
                    }
                    return new Date(time.replace(/-/g, '/'))
                }
                default:
                    return new Date(time)
            }
        },
        formatDate: function(date, format = 'yyyy/MM/dd hh:mm:ss') {
            const that = this
            if (!date && date !== 0) {
                return ''
            }
            date = that.getDate(date)
            const dateObj = {
                year: date.getFullYear(),
                month: date.getMonth() + 1,
                day: date.getDate(),
                hour: date.getHours(),
                minute: date.getMinutes(),
                second: date.getSeconds(),
                millisecond: date.getMilliseconds()
            }
            const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/
            let flag = true
            let result = format
            while (flag) {
                flag = false
                result = result.replace(tokenRegExp, function(matched) {
                    flag = true
                    switch (matched){
                        case 'yyyy':
                            return that.yyyy(dateObj)
                        case 'yy':
                            return that.yy(dateObj)
                        case 'MM':
                            return that.MM(dateObj)
                        case 'M':
                            return that.M(dateObj)
                        case 'dd':
                            return that.dd(dateObj)
                        case 'd':
                            return that.d(dateObj)
                        case 'hh':
                            return that.hh(dateObj)
                        case 'h':
                            return that.h(dateObj)
                        case 'mm':
                            return that.mm(dateObj)
                        case 'm':
                            return this.m(dateObj)
                        case 'ss':
                            return that.ss(dateObj)
                        case 's':
                            return that.s(dateObj)
                        case 'SSS':
                            return that.SSS(dateObj)
                        case 'SS':
                        case 'S':
                            return that.S(dateObj)
                    }
                })
            }
            return result
        },
        friendlyDate: function (time, {
            locale = 'zh',
            threshold = [60000, 3600000],
            format = 'yyyy/MM/dd hh:mm:ss'
        }){
            const that = this
            if (time === '-') {
                return time
            }
            if (!time && time !== 0) {
                return ''
            }
            const localeText = {
                zh: {
                    year: '年',
                    month: '月',
                    day: '天',
                    hour: '小时',
                    minute: '分钟',
                    second: '秒',
                    ago: '前',
                    later: '后',
                    justNow: '刚刚',
                    soon: '马上',
                    template: '{num}{unit}{suffix}'
                },
                en: {
                    year: 'year',
                    month: 'month',
                    day: 'day',
                    hour: 'hour',
                    minute: 'minute',
                    second: 'second',
                    ago: 'ago',
                    later: 'later',
                    justNow: 'just now',
                    soon: 'soon',
                    template: '{num} {unit} {suffix}'
                }
            }
            const text = localeText[locale] || localeText.zh
            let date = that.getDate(time)
            let ms = date.getTime() - Date.now()
            let absMs = Math.abs(ms)
            if (absMs < threshold[0]) {
                return ms < 0 ? text.justNow : text.soon
            }
            if (absMs >= threshold[1]) {
                return that.formatDate(date, format)
            }
            let num
            let unit
            let suffix = text.later
            if (ms < 0) {
                suffix = text.ago
                ms = -ms
            }
            const seconds = Math.floor((ms) / 1000)
            const minutes = Math.floor(seconds / 60)
            const hours = Math.floor(minutes / 60)
            const days = Math.floor(hours / 24)
            const months = Math.floor(days / 30)
            const years = Math.floor(months / 12)
            switch (true) {
                case years > 0:
                    num = years
                    unit = text.year
                    break
                case months > 0:
                    num = months
                    unit = text.month
                    break
                case days > 0:
                    num = days
                    unit = text.day
                    break
                case hours > 0:
                    num = hours
                    unit = text.hour
                    break
                case minutes > 0:
                    num = minutes
                    unit = text.minute
                    break
                default:
                    num = seconds
                    unit = text.second
                    break
            }

            if (locale === 'en') {
                if (num === 1) {
                    num = 'a'
                } else {
                    unit += 's'
                }
            }
            return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g,
                suffix)
        }
    }
});
